package com.qf.im.aspect;

import com.qf.im.base.Codes;
import com.qf.im.exception.ServiceException;
import com.qf.im.utils.JwtUtils;
import com.qf.im.utils.UserUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 用户认证的切面 - 一定要被扫描
 *
 * 增强：
 *  - 前置增强 @Before
 *  - 后置成功增强 @AfterReturning
 *  - 后置完成增强 @After
 *  - 后置异常增强 @AfterThrowing
 *  - 环绕增强 @Around
 *
 * execution() - 方法路径的切点表达式
 * @annotation - 自定义注解的切点表达式
 * @within
 */
@Aspect
@Component
public class AuthAspect {


    /**
     * 请求认证的环绕增强
     *
     * @annotation(com.qf.im.aspect.annotation.AuthReq) - 只要标记了@AuthReq注解的方法就会被增强
     *
     * @return
     */
    @Around("@annotation(com.qf.im.aspect.annotation.AuthReq)")
    public Object authHandler(ProceedingJoinPoint joinPoint) throws Throwable {

        try {
            //System.out.println("前置增强....");
            //1、获取请求头
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
            String loginToken = request.getHeader("Logintoken");

            //没有令牌则直接返回异常信息
            if (!StringUtils.hasLength(loginToken)) {
                throw new ServiceException(Codes.NO_LOGIN);
            }

            //2、解析令牌
            //3、获取用户id
            Integer uid = JwtUtils.parseJwtToken(loginToken, "uid");
            System.out.println("获取到用户id：" + uid);
            //4、将用户id传递给ThreadLocal
            UserUtils.setUid(uid);

            //放行
            Object result = joinPoint.proceed();
//            System.out.println("后置成功增强....");
            return result;
        } catch (Throwable e) {
//            System.out.println("后置异常增强....");
            throw e;
        } finally {
//            System.out.println("后置完成增强....");
            //清空ThreadLocal
            UserUtils.clear();
        }
    }


//    public static void main(String[] args) {
//        ThreadLocal threadLocal = new ThreadLocal();
//        threadLocal.set("Hello");//方法1
//
//        //开了一个线程
//        new Thread(() -> {
//
//            threadLocal.set("World");
//
//            Object value = threadLocal.get();
//            System.out.println("子线程打印：" + value);
//
//        }).start();
//
//        try {
//            Thread.sleep(500);
//        } catch (InterruptedException e) {
//            throw new RuntimeException(e);
//        }
//
//        Object value = threadLocal.get();//方法10
//        System.out.println("主线程打印：" + value);
//    }

}
